# -*- coding: utf-8 -*-
"""
共用的单据信息类，如生产订单、锅单、检验单、配方调整单、产品入库单等。
核心功能：从数据库获取单据配置信息并处理父子表关系数据。

@Time    : 2023/2/18 7:18
@Author  : 徐良
@File    : commonBillClass.py
"""

from typing import Dict, List, Optional, Any
from baseClass.tools.tableToList import FcToDict
from baseClass.model.editableQueryModel import EditableSqlModel
from domainAndEnum.domainFunction import DomainList
import re

class CommonBillClass:
    """
    单据信息通用工作类（精简版）
    核心功能：
    - 通过create_table_work_class()方法获取父子表配置数据
    - 数据存储在list(主表)和child_list(子表)属性中
    """

    def __init__(self):
        """初始化空数据容器"""
        super().__init__()
        self.child_list: Optional[List[Dict[str, Any]]] = None
        self.list: Optional[List[Dict[str, Any]]] = None

    def create_table_work_class(self, ms_dict: Dict[str, Any]) -> None:
        """
        核心方法：根据配置获取父子表数据
        参数msDict支持两种模式：
        1. 报表模式（含rpt键）:
           - 直接使用sqlF和sqlC作为查询SQL
        2. 配置表模式：
           - 根据msFNumber查询主表
           - 自动关联查询子表
           - 可通过pTableName/cTableName自定义表名
        """
        if 'rpt' in ms_dict:
            # 报表模式直接使用预设SQL
            query_dict = {
                'fTableSql': self._sanitize_sql(ms_dict['sqlF']),
                'cTableSql': self._sanitize_sql(ms_dict['sqlC'])
            }
        else:
            # 配置表模式动态构建SQL
            num = ms_dict['ms_number']
            ptable = ms_dict.get('pTableName', 't_tableList')
            ctable = ms_dict.get('cTableName', 't_tableListChild')

            query_dict = {
                'fTableSql': f"SELECT * FROM {ptable} WHERE fnumber='{self._escape_sql_value(num)}'",
                'cTableSql': f"SELECT * FROM {ctable} WHERE fentityid IN ({{ids}}) ORDER BY Fxh"
            }

        # 获取数据并存储
        result = FcToDict(**query_dict).get_list_dict()
        self.list = result['list']
        self.child_list = result['childList']

    @staticmethod
    def _sanitize_sql(sql: str) -> str:
        """SQL语句基础清洗（静态方法）"""
        return re.sub(r'[;\'\"]', '', sql.strip())

    @staticmethod
    def _escape_sql_value(value: str) -> str:
        """SQL值转义（静态方法）"""
        return value.replace("'", "''")

    # region 内部方法

    def _get_father_record(self, table_name: str) -> Optional[Dict[str, Any]]:
        """根据表名查找父表记录"""
        if not self.list:
            return None
        return next((row for row in self.list if row['fname'].lower() == table_name.lower()), None)

    def _get_child_records(self, fid: str) -> List[Dict[str, Any]]:
        """根据父表 ID 获取子表字段结构记录列表"""
        if not self.child_list:
            return []
        return [item for group in self.child_list for item in group if str(item['fentityid']) == fid]

    def _get_father_field(self, table_name: str, key: str, default: Any = '') -> Any:
        """获取父表字段值"""
        record = self._get_father_record(table_name)
        return record.get(key, default) if record else default

    def _get_child_field_list(self, table_name: str, key: str) -> List[Any]:
        """获取子表字段列表"""
        record = self._get_father_record(table_name)
        if not record:
            return []
        fid = str(record['fid'])
        children = self._get_child_records(fid)
        return [child.get(key, '').strip() if isinstance(child.get(key), str) else child.get(key) for child in
                children]

    # endregion


    # region 公共父字段访问接口
    def get_father_value(self, table_name: str, key: str) -> Any:
        return self._get_father_field(table_name, key)

    def get_child_value_list(self, table_name: str, key: str) -> List[Any]:
        return self._get_child_field_list(table_name, key)

    # endregion


    # region 父表字段访问接口
    def get_sql(self, table_name:str) -> str:
        """
        获取父表sql
        :param table_name:父表名称
        :return: str
        """
        return self._get_father_field(table_name, 'fsql')

    def get_date_field_name(self, table_name:str) -> str:
        """
        获取查询条件中的日期字段名
        :param table_name:父表名称
        :return:
        """
        return self._get_father_field(table_name, 'fdatename')

    def get_window_title(self, table_name: str) -> str:
        """
        获取FwindowTitle字段信息
        :param table_name:
        :return:
        """
        return self._get_father_field(table_name, 'fwindowtitle')

    def get_description(self, table_name: str) -> str:
        """
        获取FDescription字段信息
        :param table_name:
        :return:
        """
        return self._get_father_field(table_name, 'fdescription')

    def get_label_title(self, table_name: str) -> str:
        """
        获取标签内容
        :param table_name:
        :return:
        """
        return self._get_father_field(table_name, 'flabeltitle')

    def get_print_rpt_number(self,table_name: str) -> str:
        """
        获取单据打印预览的编码
        :param table_name:
        :return:
        """
        return self._get_father_field(table_name, 'fprintrptnumber')

    # endregion


    # region 子字段访问接口
    def get_field_list(self, table_name: str) -> List[Any]:
        return self.get_child_value_list(table_name, 'ffield')

    def get_field_type_list(self, table_name: str) -> List[Any]:
        return self.get_child_value_list(table_name, 'ffieldtype')

    def get_field_widget_list(self, table_name: str) -> List[Any]:
        return self.get_child_value_list(table_name, 'fwidget')

    def get_fields_name_list(self, table_name: str) -> List[Any]:
        return self.get_child_value_list(table_name, 'ffieldname')

    def get_fields_edit_list(self, table_name: str) -> List[Any]:
        return self.get_child_value_list(table_name, 'fisedit')

    def get_field_domain_list(self, table_name: str) -> List[Any]:
        domain_str_list = self.get_child_value_list(table_name, 'fdomain')
        domain_list = []
        for d_str in domain_str_list:
            if d_str in domain_str_list:
                if d_str in ['', None]:
                    domain_list.append('')
                elif d_str == 'DomainList':
                    d_object = DomainList()
                    d_list = d_object.get_domain_list()
                    domain_list.append(d_list)
                else:
                    d_list = self.get_domain_list(d_str)
                    domain_list.append(d_list)

        return domain_list

    def get_fields_visible_list(self, table_name: str) -> List[Any]:
        return self.get_child_value_list(table_name, 'fisvisible')

    def get_align_list(self, table_name: str) -> List[Any]:
        return self.get_child_value_list(table_name, 'falign')

    def get_column_width_list(self, table_name: str) -> List[Any]:
        return self.get_child_value_list(table_name, 'ftablewidth')

    def get_tree_column_width_list(self, table_name: str) -> List[Any]:
        return self.get_child_value_list(table_name, 'ftreewidth')

    def get_join_sql_list(self, table_name: str) -> List[Any]:
        return self.get_child_value_list(table_name, 'fjoinsql')

    def get_status_field_name(self, table_name: str) -> str:
        """
        获取状态字段名
        :param table_name:
        :return:
        """
        return self.get_father_value(table_name, 'fstatusfieldname')

    def get_color_group(self, table_name: str) -> str:
        """
        获取颜色组
        :param table_name:
        :return:
        """
        return self.get_father_value(table_name, 'fcolorgroup')

    def get_enum_class(self, table_name: str) -> str:
        """
        获取枚举类
        :param table_name:
        :return:
        """
        return self.get_father_value(table_name, 'fenumclass')

    def get_option_field(self, table_name: str) -> str:
        """获取条件选择的字段名"""
        return self.get_father_value(table_name, 'fselfield')

    def get_option_value(self, table_name: str) -> List[str]:
        """
        获取条件选择字段的内容
        :param table_name:
        :return:
        """
        return self.get_father_value(table_name, 'fselvalue')

    def get_is_f7_list(self, table_name: str) -> List[Any]:
        return self.get_child_value_list(table_name, 'fisf7')

    def get_f7_str_list(self, table_name: str) -> List[Any]:
        return self.get_child_value_list(table_name, 'ff7str')

    def get_col_by_field(self, table_name: str, field_name: str) -> int:
        """根据字段名获取字段在列表中的索引"""
        field_list = self.get_field_list(table_name)
        try:
            return field_list.index(field_name)
        except ValueError:
            return -1

    def get_is_edit(self, row: int, table_name: str) -> int:
        """判断某行字段是否可编辑"""
        edit_list = self.get_fields_edit_list(table_name)
        return edit_list[row] if 0 <= row < len(edit_list) else 0

    def get_delegate_dict(self, sql_name: str, p_dict: Dict[str, Any]) -> Dict[str, Any]:
        """
        获取代理的字典
        :param sql_name:
        :param p_dict:
        :return:
        """
        status_field_name = self.get_status_field_name(sql_name)
        color_group = self.get_color_group(sql_name)
        enum_class = self.get_enum_class(sql_name)
        option_field = self.get_option_field(sql_name)
        option_value = self.get_option_value(sql_name)

        if status_field_name != '':
            p_dict['statusFieldName'] = status_field_name
            p_dict['colorGroup'] = color_group
            p_dict['enumClass'] = enum_class

        if option_field != '':
            p_dict['optionField'] = option_field
            p_dict['optionValue'] = option_value

        return p_dict

    # endregion


    # region  通用方法

    def get_edit_model_by_sql(self, sql: str, sql_name: str) -> EditableSqlModel:
        """
        按给定的sql, 获取红蓝字model
        :param sql_name: 取得单表配制的信息的sqlName
        :param sql:
        :return:
        """

        model = EditableSqlModel(sql=sql)

        return model


    # endregion